package com.gxar.file.server.base.interception;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gxar.common.entity.Result;
import com.gxar.common.entity.SystemCodeEnum;
import com.gxar.common.entity.login.LoginUserThread;
import com.gxar.common.entity.login.UserProfile;
import com.gxar.file.server.base.common.constant.UserConstant;
import com.gxar.file.server.base.common.properties.UserProperties;
import com.gxar.file.server.base.reference.UserReference;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

/**
 * 登录拦截器
 * 校验用户登录状态,将用户信息放入线程对象
 *
 * @author Linsy
 * @version 1.0
 * @created 2023/6/20
 */
@Component
@Slf4j
public class LoginInterception implements HandlerInterceptor {

    @Resource
    private UserProperties userProperties;
    @Resource
    private UserReference userReference;

    @Override
    public boolean preHandle(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) throws Exception {
        // 获取token
        String token = request.getHeader(UserConstant.TOKEN_HEADER_NAME);
        String userId = StringUtils.isNotBlank(request.getHeader(UserConstant.CENTER_USER_ID)) ? request.getHeader(UserConstant.CENTER_USER_ID) : request.getHeader(UserConstant.USER_ID);
        if (StringUtils.isBlank(token) || StringUtils.isBlank(userId)) {
            returnNoLogin(response);
            return false;
        }
        // 对登录信息进行校验
        JSONObject resultObject = userReference.checkSessionService(userId, token);
        Object data = resultObject.get("data");
        if (Objects.isNull(data)) {
            log.error("用户未登陆,查询登录状态data为空");
            returnNoLogin(response);
            return false;
        }
        JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(data));
        Boolean isLogin = jsonObject.getBoolean("is_login");
        if (!isLogin) {
            log.error("用户未登陆,is_login不为true");
            returnNoLogin(response);
            return false;
        }
        UserProfile userProfile = new UserProfile();
        userProfile.setId(Long.parseLong(userId));
        // 用户已登录,将用户信息放入线程对象
        JSONObject profileJsonObject = userReference.profileService(userId, token);
        Object profileData = profileJsonObject.get("data");
        if (Objects.nonNull(profileData)) {
            JSONObject profileDateObject = JSON.parseObject(JSON.toJSONString(profileData));
            Object profileObject = profileDateObject.get("profile");
            if (Objects.nonNull(profileObject)) {
                JSONObject profile = JSON.parseObject(JSON.toJSONString(profileObject));
                userProfile.setEmail(profile.getString("email"));
                userProfile.setUsername(profile.getString("username"));
                userProfile.setNickname(profile.getString("nickname"));
                userProfile.setRegTime(profile.getLong("reg_time"));
                userProfile.setAvatar(profile.getString("avatar"));
                userProfile.setMobile(profile.getString("mobile"));
                userProfile.setSex(profile.getInteger("sex"));
            }
        }
        // 存放用户线程对象
        LoginUserThread.put(userProfile);
        // 放行
        return true;
    }

    /**
     * 返回未登录的错误信息
     *
     * @param response ServletResponse
     */
    private void returnNoLogin(HttpServletResponse response) throws IOException {
        try (ServletOutputStream outputStream = response.getOutputStream()) {
            // 设置返回401 和响应编码
            response.setStatus(401);
            response.setContentType("Application/json;charset=utf-8");
            // 构造返回响应体
            Result<Object> result = Result.error(SystemCodeEnum.UN_AUTH);
            String resultString = JSON.toJSONString(result);
            outputStream.write(resultString.getBytes(StandardCharsets.UTF_8));
        }
    }

    /**
     * preHandle 返回true时清理对象
     *
     * @param request  请求
     * @param response 响应
     * @param handler  handler
     * @param ex       异常
     */
    @Override
    public void afterCompletion(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, @Nullable Exception ex) {
        // 释放用户线程对象
        LoginUserThread.remove();
    }

}